package com.dxysun.spring.aop;

import com.dxysun.spring.aop.aspect.DXYAdvice;
import com.dxysun.spring.aop.support.DXYAdvisedSupport;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;

/**
 * Created by Tom.
 */
public class DXYJdkDynamicAopProxy implements InvocationHandler, DXYAopProxy
{
	private DXYAdvisedSupport config;

	public DXYJdkDynamicAopProxy(DXYAdvisedSupport config)
	{
		this.config = config;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
	{
		Map<String, DXYAdvice> advices = config.getAdvices(method, null);

		Object returnValue;
		try
		{
			invokeAdivce(advices.get("before"));

			returnValue = method.invoke(this.config.getTarget(), args);

			invokeAdivce(advices.get("after"));
		}
		catch (Exception e)
		{
			invokeAdivce(advices.get("afterThrow"));
			throw e;
		}

		return returnValue;
	}

	private void invokeAdivce(DXYAdvice advice)
	{
		try
		{
			advice.getAdviceMethod().invoke(advice.getAspect());
		}
		catch (IllegalAccessException e)
		{
			e.printStackTrace();
		}
		catch (InvocationTargetException e)
		{
			e.printStackTrace();
		}
	}

	@Override
	public Object getProxy()
	{
		return Proxy.newProxyInstance(this.getClass().getClassLoader(), this.config.getTargetClass().getInterfaces(),
				this);
	}

	@Override
	public Object getProxy(ClassLoader classLoader)
	{
		return Proxy.newProxyInstance(classLoader, this.config.getTargetClass().getInterfaces(), this);
	}
}
